library(igraph)
library(visNetwork)
library(dplyr)
library(ggiraph)
library(ggraph)
library(ggplot2)‘A Song of Ice and Fire’ Network Analysis and Visualization with R
This project involves the creation and analysis of network graphs based on the characters from ‘A Song of Ice and Fire’ by George R. R. Martin. Using a provided .csv file containing the edges of the network, undirected weighted graphs will be constructed with igraph in R. The analysis includes exploring the graph’s properties, such as the number of vertices and edges, diameter, triangles, and various centrality measures. Additionally, the project involves visualizing the entire network and a subgraph of characters with a high degree of connections, calculating edge densities, and ranking characters based on PageRank values. Key characters Jon Snow is examined in terms of closeness and betweenness centrality, with insights provided on the results.
Introduction
“A Song of Ice and Fire” is set in a fictional world with unpredictable, years-long seasons. Three centuries prior, the Targaryen dynasty united the Seven Kingdoms of Westeros using dragons to establish their dominance. Their reign ended with Robert Baratheon’s rebellion, which killed the last Targaryen king, Aerys II, and saw Robert crowned king.
The series begins 15 years later, as the struggle for the Iron Throne ensues following King Robert’s death. His heir, Joffrey, is proclaimed king, but Lord Eddard Stark discovers Joffrey’s illegitimacy and is executed for challenging his claim. This ignites the War of the Five Kings, with factions vying for control and two regions seeking independence.
In the far north, the Night’s Watch guards a massive ice wall against supernatural Others and wildlings, with Jon Snow, Eddard’s bastard son, rising to lead them. Meanwhile, Daenerys Targaryen, the exiled daughter of Aerys II, gains power in Essos by hatching dragons and conquering Slaver’s Bay, aiming to reclaim her ancestral throne in Westeros.
- Summary of A Song of Ice and Fire Novels
| # | Book Title | Pages | Chapters | Words | Audio | US release |
|---|---|---|---|---|---|---|
| 1 | A Game of Thrones | 694 | 73 | 292,727 | 33 h 53 min | August 1996 |
| 2 | A Clash of Kings | 768 | 70 | 318,903 | 37 h 17 min | February 1999 |
| 3 | A Storm of Swords | 973 | 82 | 414,604 | 47 h 37 min | November 2000 |
| 4 | A Feast for Crows | 753 | 46 | 295,032 | 31 h 10 min | November 2005 |
| 5 | A Dance with Dragons | 1056 | 73 | 414,788 | 48 h 56 min | July 2011 |
| 6 | The Winds of Winter | Forthcoming | - | - | - | - |
| 7 | A Dream of Spring | Forthcoming | - | - | - | - |
| Total | 4,244 | 344 | 1,736,054 | 198 h 53 min | 1996–present |
- Number of Chapters per Point-of-View Character in A Song of Ice and Fire Series
| POV Character | Game | Clash | Storm | Feast | Dance | (Winds) | Sum |
|---|---|---|---|---|---|---|---|
| Bran Stark | 7 | 7 | 4 | 3 | - | - | 21 |
| Catelyn Stark | 11 | 7 | 7 | - | - | - | 25 |
| Daenerys Targaryen | 10 | 5 | 6 | 10 | - | - | 31 |
| Eddard Stark | 15 | - | - | - | - | - | 15 |
| Jon Snow | 9 | 8 | 12 | 13 | - | - | 42 |
| Arya Stark | 5 | 10 | 13 | 3 | 2 | ≥1[57] | ≥34 |
| Tyrion Lannister | 9 | 15 | 11 | - | 12 | ≥2[103] | ≥49 |
| Sansa Stark | 6 | 8 | 7 | 3 | - | ≥1[57] | ≥25 |
| Davos Seaworth | - | 3 | 6 | - | 4 | - | 13 |
| Theon Greyjoy | - | 6 | - | 7 | - | ≥1[62] | ≥14 |
| Jaime Lannister | - | - | 9 | 7 | 1 | - | 17 |
| Samwell Tarly | - | - | 5 | 5 | - | - | 10 |
| Aeron Greyjoy | - | - | 2 | - | ≥1[59] | - | ≥3 |
| Areo Hotah | - | 1 | 1 | - | ≥1[104] | - | ≥3 |
| Cersei Lannister | - | - | 10 | 2 | - | - | 12 |
| Brienne of Tarth | - | - | 8 | - | - | - | 8 |
| Asha Greyjoy | - | - | 1 | 3 | - | - | 4 |
| Arys Oakheart | - | - | 1 | - | - | - | 1 |
| Victarion Greyjoy | - | - | 2 | 2 | - | ≥1[103] | ≥5 |
| Arianne Martell | - | - | 2 | - | ≥2[57] | - | ≥4 |
| Quentyn Martell | - | - | - | 4 | - | - | 4 |
| Jon Connington | - | - | - | 2 | - | - | 2 |
| Melisandre | - | - | - | 1 | - | - | 1 |
| Barristan Selmy | - | - | - | 4 | - | ≥2[105][106] | ≥6 |
| Prologue/Epilogue | 1/– | 1/– | 1/1 | 1/– | 1/1 | 1/TBD | ≥8 |
| Total (characters) | 73 (9) | 70 (10) | 82 (12) | 46 (13) | 73 (18) | ≥13 (≥9) | ≥357 (≥24) |
This table illustrates the number of chapters each point-of-view character has in each book of the series, along with the total chapters and character count.
‘A Song of Ice and Fire’ network
Let’s dive into the character network and analyze the existing connections, using R and igraph. ## Importing Libraries
Importing data
data<-read.csv('asoiaf-all-edges.csv')
data<-data[,c(1,2,5)]Creating an undirected weighted graph
g<-graph_from_data_frame(data,directed = F)Network Properties
The number of vertices of the graph
vcount(g)[1] 796
The list of vertices of the graph
V(g)+ 796/796 vertices, named, from 398c0c8:
[1] Addam-Marbrand
[2] Aegon-Frey-(son-of-Stevron)
[3] Aegon-I-Targaryen
[4] Aegon-Targaryen-(son-of-Rhaegar)
[5] Aegon-V-Targaryen
[6] Aemon-Targaryen-(Dragonknight)
[7] Aemon-Targaryen-(Maester-Aemon)
[8] Aenys-Frey
[9] Aeron-Greyjoy
[10] Aerys-I-Targaryen
+ ... omitted several vertices
The number of edges of the graph
ecount(g)[1] 2823
The list of edges of the graph
E(g)+ 2823/2823 edges from 398c0c8 (vertex names):
[1] Addam-Marbrand --Brynden-Tully
[2] Addam-Marbrand --Cersei-Lannister
[3] Addam-Marbrand --Gyles-Rosby
[4] Addam-Marbrand --Jaime-Lannister
[5] Addam-Marbrand --Jalabhar-Xho
[6] Addam-Marbrand --Joffrey-Baratheon
[7] Addam-Marbrand --Kevan-Lannister
[8] Addam-Marbrand --Lyle-Crakehall
[9] Addam-Marbrand --Oberyn-Martell
[10] Addam-Marbrand --Tyrion-Lannister
+ ... omitted several edges
The diameter of the graph
diameter(g)[1] 53
The number of triangles in the graph
length(triangles(g))/3 [1] 5655
Number of edges with weight more than 12
sum(E(g)$weight > 12)[1] 610
Top-10 characters by degree
head(sort(degree(g), decreasing = TRUE), 10) Tyrion-Lannister Jon-Snow Jaime-Lannister Cersei-Lannister
122 114 101 97
Stannis-Baratheon Arya-Stark Catelyn-Stark Sansa-Stark
89 84 75 75
Eddard-Stark Robb-Stark
74 74
Top-10 characters by weighted degree
head(sort(strength(g,weights = E(g)$weight), decreasing = TRUE), 10) Tyrion-Lannister Jon-Snow Cersei-Lannister Joffrey-Baratheon
2873 2757 2232 1762
Eddard-Stark Daenerys-Targaryen Jaime-Lannister Sansa-Stark
1649 1608 1569 1547
Bran-Stark Robert-Baratheon
1508 1488
Top-10 characters by local clustering coefficient
head(sort(transitivity(g, type = "local"), decreasing = TRUE), 10)Aegon-Frey-(son-of-Stevron) Albett
1 1
Alerie-Hightower Allar-Deem
1 1
Alys-Karstark Alysane-Mormont
1 1
Amabel Arron
1 1
Baelor-Blacktyde Baelor-I-Targaryen
1 1
The global clustering coefficient of the graph
transitivity(g,type = 'global')[1] 0.2090367
Subgraph
The entire network
set.seed(23)
plot(
g,
vertex.label = NA,
edge.width = E(g)$weight/100,
vertex.color='lightblue',
vertex.size = 1,
edge.color = "black",
vertex.frame.color = "black",
edge.curved = 0.1,
layout = layout_with_fr,
main = "‘A Song of Ice and Fire’ network Plot"
)Vertices that have 9 or more connections
- Selecting the vertices with 9 or more connections
sub_nodes<-V(g)[degree(g) >= 9]- Creating a sub-graph of the selected vertices
subgraph <- induced_subgraph(g, sub_nodes)- Plotting the sub-graph
set.seed(23)
plot(
subgraph,
vertex.label=NA,
edge.width = E(subgraph)$weight/80,
vertex.color='lightblue',
vertex.size = 2,
edge.color = "black",
vertex.frame.color = "black",
edge.curved = 0.1,
layout = layout_with_fr,
main = "‘A Song of Ice and Fire’ network Plot \nfor characters with 9 or more connections"
)Edge density
- Edge density of the entire graph
edge_density(g)[1] 0.008921968
- Edge density of the sub-graph
edge_density(subgraph)[1] 0.09494239
Centrality
Closeness Centrality
head(sort(closeness(g, normalized = TRUE),decreasing = T),15) Jaime-Lannister Robert-Baratheon Stannis-Baratheon Theon-Greyjoy
0.09587554 0.09244186 0.09118018 0.09111748
Jory-Cassel Tywin-Lannister Tyrion-Lannister Cersei-Lannister
0.09075342 0.09044369 0.08984066 0.08981021
Brienne-of-Tarth Jon-Snow Joffrey-Baratheon Rodrik-Cassel
0.08939615 0.08895603 0.08785501 0.08773866
Eddard-Stark Doran-Martell Robb-Stark
0.08682831 0.08654474 0.08653532
- Jon Snow’s relatively high rank in the closeness scores suggests that he has strong connections with other characters within the narrative. This is consistent with Jon Snow’s prominent role in the “A Song of Ice and Fire” series as one of the central protagonists.
There are several factors that could contribute to Jon Snow’s high closeness score:
Relationships: Jon Snow interacts with a wide range of characters throughout the series, including members of his own family (such as Eddard Stark and his siblings), his sworn brothers in the Night’s Watch, key political figures (such as Stannis Baratheon), and other major players in the series (such as Tyrion Lannister and Daenerys Targaryen). These interactions create connections and relationships that contribute to his overall closeness score.
Story Arcs: Jon Snow’s storyline intersects with many major plotlines in the series, particularly those involving the Night’s Watch, the Wall, and the threat of the White Walkers. His actions and decisions often have far-reaching consequences that impact other characters and events in the story, further increasing his closeness to various elements of the narrative.
Betweeness Centrality
head(sort(betweenness(g, normalized = TRUE),decreasing = T),15) Jon-Snow Theon-Greyjoy Jaime-Lannister Daenerys-Targaryen
0.13211964 0.12326573 0.11677631 0.09419228
Stannis-Baratheon Robert-Baratheon Tyrion-Lannister Cersei-Lannister
0.09291440 0.09252286 0.09162375 0.07734002
Tywin-Lannister Robb-Stark Arya-Stark Barristan-Selmy
0.06358359 0.06295788 0.06132325 0.05630053
Eddard-Stark Sansa-Stark Brienne-of-Tarth
0.05562270 0.05042041 0.04947298
- Jon Snow has the highest betweenness centrality score, indicating that he often serves as a central figure who connects various characters within the story. This aligns with Jon’s role as a central protagonist who interacts with a wide range of characters from different factions and storylines.
Ranking and Visualization
- PageRank values
page_rank<-page_rank(g, weights = E(g)$weight)$vector- Network Plot with PageRank
set.seed(23)
plot(
g,
vertex.label = NA,
edge.width = E(g)$weight/100,
vertex.color='lightblue',
vertex.size = page_rank*100,
edge.color = "black",
vertex.frame.color = "black",
edge.curved = 0.1,
layout = layout_with_fr,
main = "‘A Song of Ice and Fire’ network Plot",
sub="Size = PageRank"
)- Subgraph Plot with PageRank
set.seed(23)
plot(
subgraph,
vertex.label = NA,
edge.width = E(subgraph)$weight/80,
vertex.color='lightblue',
vertex.size = page_rank[sub_nodes]*150,
edge.color = "black",
vertex.frame.color = "black",
edge.curved = 0.1,
layout = layout_with_fr,
main = "‘A Song of Ice and Fire’ network Plot \nfor characters with 9 or more connections",
sub="Size = PageRank"
)